package com.example.geoserverdemo.util;

import com.example.geoserverdemo.dto.FeatureType;
import com.example.geoserverdemo.param.DataStoreParam;
import com.example.geoserverdemo.param.FeatureTypeParam;
import com.example.geoserverdemo.param.WorkspaceParam;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PublishHelper {
    private  WebClient webClient;

    public PublishHelper(String baseUrl){
        webClient = WebClient.create(baseUrl);
    }

    public  String uploadWorkspace(String name){
        WorkspaceParam param = new WorkspaceParam();
        Map<String, String> workspace = new HashMap<String, String>();
        workspace.put("name", name);
        param.setWorkspace(workspace);
        Mono<String> mp = webClient.post()
                .uri("/geoserver/rest/workspaces")
                .body(Mono.just(param), WorkspaceParam.class)
                .retrieve()
                .onStatus(HttpStatus::is4xxClientError, response -> {
                    return Mono.error(new RuntimeException(response.statusCode().value() + ":" + response.statusCode().getReasonPhrase()));
                })
                .bodyToMono(String.class);

        return mp.block();
    }

    public String uploadDataStoreTiff(String workspace, String name){
        DataStoreParam param = new DataStoreParam();
        Map<String, Object> dataStore = new HashMap<>();
        Map<String, Object> connectionParameter = new HashMap<>();
        List<Map<String, Object>> entry = new ArrayList<>();
        Map<String, Object> e1 = new HashMap<>();
        e1.put("@key", "url");
        e1.put("$", "file://E:/GISData/geopackage/testTiff.gpkg");
        Map<String, Object> e2 = new HashMap<>();
        e2.put("@key", "dbtype");
        e2.put("$", "geopkg");
        entry.add(e1);
        entry.add(e2);
        connectionParameter.put("entry", entry);

        dataStore.put("name", name);
        dataStore.put("connectionParameters", connectionParameter);
        param.setDataStore(dataStore);

        Mono<String> mp = webClient.post()
                .uri("/geoserver/rest/workspaces/" + workspace + "/datastores")
                .body(Mono.just(param), DataStoreParam.class)
                .retrieve()
                .onStatus(HttpStatus::is4xxClientError, response -> {
                    return Mono.error(new RuntimeException(response.statusCode().value() + ":" + response.statusCode().getReasonPhrase()));
                })
                .bodyToMono(String.class);
        return mp.block();
    }

    public  String uploadDataStorePG(String workspace, String dataStoreName){
        DataStoreParam param = new DataStoreParam();
        Map<String, Object> dataStore = new HashMap<>();
        Map<String, Object> connectionParameter = new HashMap<>();
        List<Map<String, Object>> entry = new ArrayList<>();
        Map<String, Object> e1 = new HashMap<>();
        e1.put("@key", "host");
        e1.put("$", "localhost");
        Map<String, Object> e2 = new HashMap<>();
        e2.put("@key", "port");
        e2.put("$", "5432");
        Map<String, Object> e3 = new HashMap<>();
        e3.put("@key", "database");
        e3.put("$", "mydb");
        Map<String, Object> e4 = new HashMap<>();
        e4.put("@key", "user");
        e4.put("$", "postgres");
        Map<String, Object> e5 = new HashMap<>();
        e5.put("@key", "passwd");
        e5.put("$", "postgres");
        Map<String, Object> e6 = new HashMap<>();
        e6.put("@key", "dbtype");
        e6.put("$", "postgis");
        entry.add(e1);
        entry.add(e2);
        entry.add(e3);
        entry.add(e4);
        entry.add(e5);
        entry.add(e6);
        connectionParameter.put("entry", entry);

        dataStore.put("name", dataStoreName);
        dataStore.put("connectionParameters", connectionParameter);
        param.setDataStore(dataStore);

        Mono<String> mp = webClient.post()
                .uri("/geoserver/rest/workspaces/" + workspace + "/datastores")
                .body(Mono.just(param), DataStoreParam.class)
                .retrieve()
                .onStatus(HttpStatus::is4xxClientError, response -> {
                    return Mono.error(new RuntimeException(response.statusCode().value() + ":" + response.statusCode().getReasonPhrase()));
                })
                .bodyToMono(String.class);
        return mp.block();
    }

    public  String uploadFeatureType(String workSpace, String dataStore, String name){
        FeatureType type = new FeatureType();
        type.setName(name);
        type.setNativeName("china_boundary");
        type.setNativeCRS("GEOGCS[\"WGS 84\"), \r\n DATUM[\"World Geodetic System 1984\"), \r\n SPHEROID[\"WGS 84\"), 6378137.0), 298.257223563), AUTHORITY[\"EPSG\"),\"7030\"]]), \r\n AUTHORITY[\"EPSG\"),\"6326\"]]), \r\n PRIMEM[\"Greenwich\"), 0.0), AUTHORITY[\"EPSG\"),\"8901\"]]), \r\n UNIT[\"degree\"), 0.017453292519943295]), \r\n AXIS[\"Geodetic longitude\"), EAST]), \r\n AXIS[\"Geodetic latitude\"), NORTH]), \r\n AUTHORITY[\"EPSG\"),\"4326\"]]");
        type.setSrs("EPSG:4326");
        type.setProjectionPolicy("FORCE_DECLARED");
        type.setEnabled(true);
        type.setServiceConfiguration(false);
        type.setSimpleConversionEnabled(false);
        type.setInternationalTitle("");
        type.setInternationalAbstract("");
        type.setMaxFeatures(0);
        type.setNumDecimals(0);
        type.setPadWithZeros(false);
        type.setForcedDecimal(false);
        type.setOverridingServiceSRS(false);
        type.setSkipNumberMatched(false);
        type.setCircularArcPresent(false);


        FeatureTypeParam param = new FeatureTypeParam();
        param.setFeatureType(type);
        Mono<String> mp = webClient.post()
                .uri("/geoserver/rest/workspaces/" + workSpace + "/datastores/" + dataStore + "/featuretypes")
                .body(Mono.just(param), FeatureType.class)
                .retrieve()
                .onStatus(HttpStatus::is4xxClientError, response -> {
                    return Mono.error(new RuntimeException(response.statusCode().value() + ":" + response.statusCode().getReasonPhrase()));
                })
                .bodyToMono(String.class);
        return mp.block();
    }
}
